use proc_macro::TokenStream;
use quote::{quote, TokenStreamExt};
use syn::{parse_macro_input, Data, DeriveInput, Fields};

// 转换驼峰命名为下划线命名
pub fn snake_case(s: &str) -> String {
    let mut result = String::new();
    for (i, c) in s.chars().enumerate() {
        if c.is_uppercase() {
            if i != 0 {
                result.push('_');
            }
            result.push(c.to_lowercase().next().unwrap());
        } else {
            result.push(c);
        }
    }
    result
}

pub fn crud_derive11(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    let ident = &input.ident;
    let table_name = snake_case(&ident.to_string());

    // 获取字段
    let fields = if let Data::Struct(data) = input.data {
        match data.fields {
            Fields::Named(fields_named) => fields_named.named.into_iter().collect::<Vec<_>>(),
            _ => {
                panic!("Only named fields are supported");
            }
        }
    } else {
        panic!("Only structs are supported");
    };

    let mut field_names = Vec::new();
    let mut field_binds = Vec::new();

    for f in &fields {
        let ident = &f.ident;

        // 检查字段是否为 Option 类型
        if let syn::Type::Path(type_path) = &f.ty {
            if type_path.path.segments.last().unwrap().ident == "Option" {
                // 只有在字段有值的情况下才添加
                if let Some(value) = &f.ident {
                    field_names.push(quote!(#ident));
                    field_binds.push(quote!(self.#ident.as_ref().unwrap())); // 假设字段不为 None
                }
            } else {
                // 对于非 Option 类型，直接添加
                field_names.push(quote!(#ident));
                field_binds.push(quote!(self.#ident));
            }
        }
    }


    /*let (field_names, binds): (Vec<_>, Vec<_>) = fields
        .iter()
        .filter_map(|f| {
            let ident = &f.ident;

            // 检查字段是否为 Option 类型
            if let syn::Type::Path(type_path) = &f.ty {
                if type_path.path.segments.last().unwrap().ident == "Option" {
                    // 返回对Option字段的检查，确保只有有值时才返回
                    if let Some(value) = &f.ident {
                        Some((quote!(#ident), quote!(self.#ident.as_ref())))
                    } else {
                        None
                    }
                } else {
                    // 对于非 Option 类型，直接绑定
                    Some((quote!(#ident), quote!(self.#ident.as_ref())))
                }
            } else {
                None
            }
        })
        .filter(|(name, bind)| name.is_some()) // 过滤掉 None
        .unzip();*/

    // 生成字段名和占位符
    /* let (field_names, binds): (Vec<_>, Vec<_>) = fields
        .iter()
        .filter_map(|f| {
            let ident = &f.ident;
            // 检查字段是否为 Option 类型
            if let syn::Type::Path(type_path) = &f.ty {
                if type_path.path.segments.last().unwrap().ident == "Option" {
                    quote!(if let Some(value) = &self.#ident {
                        Some((quote!(#ident), quote!(self.#ident.as_ref())))
                        }
                        else {
                            return None;
                        }
                    );
                    // 返回字段名和绑定
                    None
                } else {
                    // 对于非 Option 类型，直接绑定
                    Some((quote!(#ident), quote!(self.#ident)))
                }
            } else {
                None
            }
        })
        .unzip(); */

    let placeholders = (0..field_names.len())
        .map(|_| "?")
        .collect::<Vec<_>>()
        .join(",");

    let gen = quote! {
        impl #ident {
            pub async fn insert(self, pool: &sqlx::Pool<sqlx::Sqlite>) -> Result<(), sqlx::Error> {
                // 构建插入 SQL 语句
                let sql = format!("INSERT INTO {} ({}) VALUES ({})",  #table_name,
                    #(stringify!(#field_names)),*,
                    #placeholders
                );
                // 构建查询并动态绑定
                let mut query = sqlx::query(&sql);
                #(
                    if let Some(value) = #field_binds {
                        query = query.bind(value);
                    }
                )*

                query.execute(pool).await?;
                Ok(())
            }
        }
    };

    gen.into()
}

pub fn crud_derive(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    let ident = &input.ident;
    let table_name = snake_case(&ident.to_string());
    // 获取字段
    let fields = if let Data::Struct(data) = input.data {
        match data.fields {
            Fields::Named(fields_named) => {
                let named = fields_named.named;
                named.into_iter().map(|f| f.ident).collect::<Vec<_>>()
            }
            _ => {
                panic!("Only named fields are supported");
            }
        }
    } else {
        panic!("Only structs are supported");
    };

    let placeholders = (0..fields.len()).map(|_| "?").collect::<Vec<_>>().join(",");

    let gen = quote! {
        impl #ident {
            pub async fn insert(self, pool: &sqlx::Pool<sqlx::Sqlite>) -> Result<(), sqlx::Error> {
                sqlx::query(format!("INSERT INTO {} ({}) VALUES ({})", stringify!(#table_name),
                    stringify!(#(#fields),*).replace(" ", ""),
                    #placeholders
                ).as_str().trim_end_matches(','))
                #(.bind(self.#fields))*
                .execute(pool)
                .await?;
                Ok(())
            }

            pub async fn read(pool: &sqlx::Pool<sqlx::Sqlite>) -> Result<Vec<#ident>, sqlx::Error> {
                let items = sqlx::query_as::<_, #ident>(format!("SELECT {} FROM {}", stringify!(#(#fields),*), stringify!(#ident)).as_str())
                    .fetch_all(pool)
                    .await?;
                Ok(items)
            }

            pub async fn update(&self, pool: &sqlx::Pool<sqlx::Sqlite>, id: i32) -> Result<(), sqlx::Error> {
                let mut query = format!("UPDATE {} SET ", stringify!(#ident));
                for field in stringify!(#(#fields),*).split(",") {
                    query.push_str(&format!("{} = ?, ", field));
                }
                query.pop(); // 移除最后的逗号
                query.pop(); // 移除最后的空格
                query.push_str(" WHERE id = ?");

                sqlx::query(&query)
                    #(.bind(self.#fields.clone()))*
                    .bind(id)
                    .execute(pool)
                    .await?;
                Ok(())
            }

            pub async fn delete(id: i32, pool: &sqlx::Pool<sqlx::Sqlite>) -> Result<(), sqlx::Error> {
                sqlx::query("DELETE FROM #name WHERE id = ?")
                    .bind(id)
                    .execute(pool)
                    .await?;
                Ok(())
            }
        }
    };

    gen.into()
}
